const PENDING = "PENDING";
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";

class Promise {
  constructor(executor) {
    // 让promise变成成功态
    this.status = PENDING; // 默认为等待态
    this.value = undefined; // 为什么成功
    this.reason = undefined; // 为什么失败
    this.onResolvedCallbacks = []; // 存放成功的回调列表
    this.onRejectedCallbacks = []; // 存放失败的回调列表
    const resolve = (value) => {
      if (this.status === PENDING) {
        this.value = value;
        this.status = FULFILLED;
        // 发布
        this.onResolvedCallbacks.forEach((fn) => fn());
      }
    };
    // 让promise变成失败态
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.reason = reason;
        this.status = REJECTED;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }
  then(onFulfilled, onRejected) {
    let promise2 = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        process.nextTick(() => {
          try {
            let x = onFulfilled(this.value); // x上一次then函数中回调的返回值
            // 决定promise2 是成功还是失败
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      }
      if (this.status === REJECTED) {
        process.nextTick(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(promise2, x, resolve, reject);
          } catch (e) {
            reject(e);
          }
        });
      }
      if (this.status === PENDING) {
        // 订阅模式
        this.onResolvedCallbacks.push(() => {
          // 额外的扩展
          process.nextTick(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
        this.onRejectedCallbacks.push(() => {
          process.nextTick(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(promise2, x, resolve, reject);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    });

    return promise2;
  }
}
// 这个规范里面有要求， 所有人的promise可以相互调用
// x 可能是别人家promise
function resolvePromise(promise2, x, resolve, reject) {
  // 我们要利用上一次then 中回调的返回值来决定 promise2是成功还是失败
  // 判断x 是不是promise 是promise就then它， 如果不是promise直接调用promise2的resolve即可
  if (promise2 === x) {
    return reject(
      new TypeError(
        "[TypeError: Chaining cycle detected for promise #<Promise>] my"
      )
    );
  }
  // 姑且认为x 肯能是promise
  if ((typeof x === "object" && x !== null) || typeof x === "function") {
    let called = false;
    try {
      let then = x.then; // 取then方法，因为promise是有then 函数的
      if (typeof then === "function") {
        then.call(
          x,
          (y) => {
            // resolvePromise
            if (called) return;
            called = true;
            resolve(y);
          },
          (r) => {
            if (called) return;
            called = true;
            // rejectPromise
            reject(r);
          }
        );
      } else {
        resolve(x); // 当作非promise对象来处理
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x); // 当作非promise对象来处理
  }
}
export default Promise;
